package com.cancer.application;

import javax.servlet.http.HttpServlet;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.cancer.biz.common.SysConfigUtils;
import com.cancer.biz.common.WeixinConfig;
import com.cancer.common.util.WeixinUtil;

import io.vertx.core.Vertx;
import io.vertx.core.VertxOptions;
import io.vertx.core.eventbus.EventBus;
import io.vertx.core.http.HttpClient;
import io.vertx.core.http.HttpClientRequest;
import io.vertx.core.json.JsonObject;

@SuppressWarnings("serial")
public class BaseServlet extends HttpServlet implements WeixinConfig {
	private static Logger logger = LoggerFactory.getLogger(BaseServlet.class);
	// 是否开始获取ticket
	private static boolean startTicket = false;
	protected final static Vertx vertx;
	static {
		VertxOptions options = new VertxOptions();
		// 最大执行时间10S,超过10s,讲触发警告
		options.setMaxEventLoopExecuteTime(10000000000L);
		vertx = Vertx.vertx(options);
	}

	public static Vertx messageChannel() {
		return BaseServlet.vertx;
	}

	public static EventBus eventBus() {
		return vertx.eventBus();
	}

	// 获取token和JsapiTicket放入内存中
	protected void getAccessTokenAndJSTicket() {
		HttpClient http = vertx.createHttpClient(options);
		String appId = SysConfigUtils.getValue("appId");
		String appSecret = SysConfigUtils.getValue("appSecret");
		String uri = "/cgi-bin/token?grant_type=client_credential&appid=" + appId + "&secret=" + appSecret;
		// 获取open id
		HttpClientRequest req = http.get(uri, resp -> {
			int scode = resp.statusCode();
			resp.bodyHandler(buff -> {
				String body = buff.toString(WeixinUtil.STR_UTF8);
				long expires_in;
				if (scode >= 200 && scode < 300) {
					// success
					JsonObject result = new JsonObject(body);
					String access_token = result.getString("access_token");
					if (access_token != null) {
						// 更新所有缓存token
						WeixinUtil.currentToken.put("currentToken", access_token);
						// 我们把过期时间提前5分钟获取
						expires_in = result.getInteger("expires_in") * 1000 - 5 * 60 * 1000;
						if (!startTicket) {
							// 开始首次获取ticket
							startTicket = true;
							getJsapiTicket();
						}
					} else {
						logger.error("WeixinAccessToken getAccessToken error: " + result.encode());
						expires_in = 10000L;
					}
				} else {
					logger.error("WeixinAccessToken getAccessToken http code: " + scode);
					// 10秒后再次尝试
					expires_in = 10000L;
				}
				vertx.setTimer(expires_in, id -> getAccessTokenAndJSTicket());
				http.close();
			});
		});
		req.setTimeout(5000);
		req.exceptionHandler(ex -> {
			logger.error("WeixinAccessToken getAccessToken error: " + ex.getMessage());
			vertx.setTimer(10000L, id -> getAccessTokenAndJSTicket());
		});
		req.end();
	}

	/**
	 * 获取腾讯jsapi ticket
	 */
	private void getJsapiTicket() {
		HttpClient http = vertx.createHttpClient(options);
		String access_token = WeixinUtil.currentToken.get("currentToken").toString();
		String uri = "/cgi-bin/ticket/getticket?access_token=" + access_token + "&type=jsapi";
		// 获取open id
		HttpClientRequest req = http.get(uri, resp -> {
			int scode = resp.statusCode();
			resp.bodyHandler(buff -> {
				String body = buff.toString(WeixinUtil.STR_UTF8);
				long expires_in;
				if (scode >= 200 && scode < 300) {
					// success
					JsonObject result = new JsonObject(body);
					String jsapi_ticket = result.getString("ticket");
					if (access_token != null) {
						// 更新所有缓存ticket
						WeixinUtil.jsapiTicket.put("currentJsTicket", jsapi_ticket);
						// 我们把过期时间提前5分钟获取
						expires_in = result.getInteger("expires_in") * 1000 - 5 * 60 * 1000;
					} else {
						logger.error("WeixinAccessToken getJsapiTicket error: " + result.encode());
						expires_in = 10000L;
					}
				} else {
					logger.error("WeixinAccessToken getJsapiTicket http code: " + scode);
					// 10秒后再次尝试
					expires_in = 10000L;
				}
				vertx.setTimer(expires_in, id -> getJsapiTicket());
				http.close();
			});
		});
		req.setTimeout(5000);
		req.exceptionHandler(ex -> {
			logger.error("WeixinAccessToken getJsapiTicket error: " + ex.getMessage());
			vertx.setTimer(10000L, id -> getJsapiTicket());
		});
		req.end();
	}
}
